/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010.

	This file is part of Maxsi Engine.

	Maxsi Engine is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi engine is distributed in the hope that it will be useful, but WITHOUT
	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
	for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Engine. If not, see <http://www.gnu.org/licenses/>.

	MaxsiEngine.dll
	A general purpose C++ library for the Maxsi Technology Project.

	MaxsiNetworking.h
	Multithreaded Networking. Very ugly. Must be replaced by the MaxsiIO System
	in the near future!

******************************************************************************/

#ifndef MaxsiNetworking_H
#define MaxsiNetworking_H

BeginMaxsiNamespace

//=============================================================================
//	Define where the MaxsiNetworking interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_ABSTRACT_BASECLASS

//=============================================================================
//	MaxsiNetworking - An interface for dealing with network I/O.
//=============================================================================
CLASSLINK MaxsiNetworking
{
	//=============================================================================
	//	Copy-pasteable interface starts here:
	//=============================================================================

public:
	virtual MaxsiHandle SyncConnectToHost(MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual size_t SyncReadSocket(MaxsiHandle Socket, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual size_t SyncWriteSocket(MaxsiHandle Socket, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual bool SyncCloseSocket(MaxsiHandle Socket) MAXSI_INTERFACE;

};

#ifdef Maxsi_Support_POSIX
//=============================================================================
//	Define where the MaxsiNetworkingPOSIX interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_ENGINE

//=============================================================================
//	MaxsiNetworkingPOSIX - An interface for dealing with network I/O.
//=============================================================================
CLASSLINK MaxsiNetworkingPOSIX : public MaxsiNetworking
{
public:
	virtual MaxsiHandle SyncConnectToHost(MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual size_t SyncReadSocket(MaxsiHandle Socket, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual size_t SyncWriteSocket(MaxsiHandle Socket, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual bool SyncCloseSocket(MaxsiHandle Socket) MAXSI_INTERFACE;

};

#endif

#ifdef Maxsi_Support_W32
//=============================================================================
//	Define where the MaxsiNetworkingW32 interface is declared.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_ENGINE

//=============================================================================
//	MaxsiNetworkingW32 - An interface for dealing with network I/O.
//=============================================================================
CLASSLINK MaxsiNetworkingW32 : public MaxsiNetworking
{
public:
	virtual MaxsiHandle SyncConnectToHost(MESTR* HostName, short Port) MAXSI_INTERFACE;
	virtual size_t SyncReadSocket(MaxsiHandle Socket, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual size_t SyncWriteSocket(MaxsiHandle Socket, BYTE* Buffer, size_t Size) MAXSI_INTERFACE;
	virtual bool SyncCloseSocket(MaxsiHandle Socket) MAXSI_INTERFACE;

};

#endif

//=============================================================================
//	Remember to reset MAXSI_INTERFACE when done with it for safety reasons.
//=============================================================================
#undef MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_RESET_IT_TO_THIS

LINK MaxsiNetworking* Networking();

typedef size_t (* MaxsiNetworkingSyncCallback)(void* UserData, BYTE* Data, size_t DataSize);

LINK MaxsiError RetrieveHTTP(MESTR* Host, MESTR* Resource, MaxsiNetworkingSyncCallback Callback, void* UserData = NULL, short Port = 80, MaxsiNetworking* Network = NULL);


// This has not been ported yet. It will be merged into Maxsi IO, first.
#if defined(Maxsi_Support_Linux)

STRUCTLINK MaxsiAsyncIOHandle
{
#ifdef Maxsi_Support_POSIX
	int	FD;
#endif
};

CLASSLINK MaxsiAsync
{
	public:
	virtual MaxsiHandle AsyncListen(short Port) = 0;
	virtual MaxsiHandle AsyncConnect(MESTR* HostName, short Port) = 0;
	virtual MaxsiHandle AsyncOpenFile(MESTR* Path, FLAGS32 Mode) = 0;
	virtual MaxsiError SetUpAsyncIOHandleCallbacks(MaxsiHandle IOHandle) = 0;
	virtual MaxsiError MainLoop() = 0;
};

#ifdef Maxsi_Support_Epoll

MAXSI_TODO("Find a better value for this suggested value for how many concurrent FDs we are going to check. Note, however, this is not a limit, just a guess on how many FDs we need, the kernel performs better if we give it a realistic value.");
#define Maxsi_Epoll_DefaultSize 8

#define MAXSI_EPOLL_STATE_READ (1<<0)
#define MAXSI_EPOLL_STATE_WRITE (1<<1)

#define MAXSI_EPOLL_IS_SERVER (1<<2)
#define MAXSI_EPOLL_IS_SOCKET_LISTENER (1<<3)

#define MAXSI_EPOLL_BUF_SIZE 64

STRUCTLINK MaxsiAsyncEpollIOHandle : MaxsiAsyncIOHandle
{
	FLAGS32	State;
	timeval Begun;
	timeval	Last;
	timeval	Now;
	FileSize_t TotalRead;
	FileSize_t TotalWritten;
	bool PrintDebug;
	long NowMS;
	long LastMS;
	long BegunMS;
	float Elapsed;
	BYTE InBuf[MAXSI_EPOLL_BUF_SIZE];
	BYTE OutBuf[MAXSI_EPOLL_BUF_SIZE];

};


CLASSLINK MaxsiAsyncEpoll : public MaxsiAsync
{
public:
	MaxsiAsyncEpoll();
	~MaxsiAsyncEpoll();

public:
	int	EpollFD;

public:
	virtual MaxsiHandle AsyncListen(short Port);
	virtual MaxsiHandle AsyncConnect(MESTR* HostName, short Port);
	virtual MaxsiHandle AsyncOpenFile(MESTR* Path, FLAGS32 Mode);
	virtual MaxsiError SetUpAsyncIOHandleCallbacks(MaxsiHandle IOHandle);
	virtual MaxsiError MainLoop();
	virtual MaxsiError DoRead(MaxsiAsyncEpollIOHandle* Handle);
	virtual MaxsiError DoWrite(MaxsiAsyncEpollIOHandle* Handle);
	virtual MaxsiError AcceptClient(MaxsiAsyncEpollIOHandle* Handle);

};
#endif

LINK MaxsiAsync* Async();

#endif

EndMaxsiNamespace

#endif
